// 将此文件内容复制到App.js，运行npm start即可查看效果。
import React, { useCallback, useContext, useState } from 'react';
import { ReactFlow, Handle, useNodesState, useEdgesState, addEdge } from 'reactflow';
import 'reactflow/dist/style.css';
import { FiDatabase, FiCloud } from 'react-icons/fi';
import { toast, Toaster } from 'react-hot-toast';

// 创建上下文用于节点更新
const NodeUpdateContext = React.createContext();

const CustomNode = ({ id, data, selected }) => {
  const setNodes = useContext(NodeUpdateContext);
  const [editingHandle, setEditingHandle] = useState(null);
  const [tempName, setTempName] = useState('');

  const handleNameChange = (handleId, newName) => {
    setNodes(nds => nds.map(node => 
      node.id === id ? {
        ...node,
        data: {
          ...node.data,
          handleNames: {
            ...node.data.handleNames,
            [handleId]: newName
          }
        }
      } : node
    ));
  };

  const startEdit = (handleId) => {
    setEditingHandle(handleId);
    setTempName(data.handleNames?.[handleId] || '');
  };

  const confirmEdit = () => {
    if (editingHandle) {
      handleNameChange(editingHandle, tempName);
      setEditingHandle(null);
    }
  };

  const renderHandle = (localId, position, type) => {
    const fullId = `${id}-${localId}`;
    const isEditing = editingHandle === fullId;
    const displayName = data.handleNames?.[fullId] || '';

    return (
      <div className={`handle-group handle-${position}`}>
        {isEditing && (
          <input
            type="text"
            value={tempName}
            onChange={(e) => setTempName(e.target.value)}
            onBlur={confirmEdit}
            onKeyPress={(e) => e.key === 'Enter' && confirmEdit()}
            autoFocus
            className="handle-input"
          />
        )}
        <Handle
          id={fullId}
          type={type}
          position={position}
          className={`!bg-${type === 'target' ? 'teal' : 'purple'}-500`}
          onDoubleClick={() => startEdit(fullId)}
          title={displayName}
        />
      </div>
    );
  };

  return (
    <div className={`custom-node ${selected ? 'selected' : ''}`}>
      {renderHandle('target-top', 'top', 'target')}
      
      <div className="node-header">
        <FiCloud className="node-icon" />
        <h3 className="node-title">{data.label}</h3>
      </div>
      <div className="node-body">
        <FiDatabase className="node-icon" />
        <span className="node-info">{data.content}</span>
      </div>

      {renderHandle('source-bottom', 'bottom', 'source')}
      {renderHandle('source-right', 'right', 'source')}
    </div>
  );
};

// 初始节点配置（保持其他内容不变，增加handleNames字段）
const initialNodes = [
  { 
    id: '1', 
    position: { x: 0, y: 0 }, 
    data: { 
      label: '开始节点',
      content: '输入数据源',
      handleNames: {
        '1-target-top': '输入',
        '1-source-bottom': '主输出',
        '1-source-right': '备选输出'
      }
    },
    type: 'custom',
  },
  { 
    id: '2', 
    position: { x: 200, y: 150 }, 
    data: { 
      label: '处理节点',
      content: '数据处理流程',
      handleNames: {
        '2-target-top': '输入',
        '2-source-bottom': '结果输出',
        '2-source-right': '日志输出'
      }
    },
    type: 'custom',
  },
];

const initialEdges = [{ 
  id: 'e1-2', 
  source: '1', 
  target: '2',
  animated: true,
  style: { stroke: '#94a3b8' },
}];

const nodeTypes = {
  custom: CustomNode,
};

// 样式增加连接点标签相关样式
const nodeStyle = `
  .custom-node {
    position: relative;
    background: linear-gradient(145deg, #ffffff, #f1f5f9);
    border-radius: 8px;
    border: 2px solid #cbd5e1;
    box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
    padding: 16px;
    min-width: 200px;
    transition: all 0.2s ease;
  }

  .custom-node.selected {
    border-color: #6366f1;
    box-shadow: 0 4px 15px rgba(99, 102, 241, 0.2);
  }

  .custom-node:hover {
    transform: translateY(-2px);
  }

  .node-header {
    display: flex;
    align-items: center;
    margin-bottom: 12px;
    border-bottom: 1px solid #e2e8f0;
    padding-bottom: 8px;
  }

  .node-title {
    margin: 0;
    font-size: 1.1rem;
    color: #1e293b;
    margin-left: 8px;
  }

  .node-body {
    display: flex;
    align-items: center;
    color: #64748b;
  }

  .node-icon {
    font-size: 1.2rem;
    margin-right: 8px;
    color: #6366f1;
  }

  .node-info {
    font-size: 0.9rem;
  }

  .react-flow__handle {
    width: 24px;
    height: 14px;
    border-radius: 3px;
    border: none;
    cursor: pointer;
    transition: background-color 0.2s;
  }
  .react-flow__handle:hover {
    filter: brightness(1.2);
  }
    /* 按位置调整具体坐标 */
.react-flow__handle[data-position="top"] {
  top: -7px !important;
  left: 50% !important;
  transform: translateX(-50%) !important;
}

.react-flow__handle[data-position="bottom"] {
  bottom: -7px !important;
  left: 50% !important;
  transform: translateX(-50%) !important;
}

.react-flow__handle[data-position="right"] {
  right: -12px !important;
  top: 50% !important;
  transform: translateY(-50%) !important;
}
  .handle-group {
    z-index: 10;
  }
  .handle-input {
    position: absolute;
    width: 80px;
    padding: 2px 4px;
    font-size: 0.8rem;
    border: 1px solid #6366f1;
    border-radius: 4px;
    background: white;
    z-index: 100;
  }
    .handle-top .handle-input {
    bottom: calc(100% + 8px);
    left: 50%;
    transform: translateX(-50%);
  }

  .handle-bottom .handle-input {
    top: calc(100% + 8px);
    left: 50%;
    transform: translateX(-50%);
  }

  .handle-right .handle-input {
    left: calc(100% + 8px);
    top: 50%;
    transform: translateY(-50%);
  }
`;


export default function App() {
  const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
  const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);

  return (
    <NodeUpdateContext.Provider value={setNodes}>
      <div style={{ height: '100vh', background: '#f8fafc' }}>
        <style>{nodeStyle}</style>
        <Toaster position="top-right" />
        <ReactFlow
          nodes={nodes}
          edges={edges}
          onNodesChange={onNodesChange}
          onEdgesChange={onEdgesChange}
          onConnect={useCallback((conn) => 
            setEdges(eds => addEdge({
              ...conn,
              animated: true,
              style: conn.sourceHandle?.endsWith('-right') 
                ? { stroke: '#ec4899' } 
                : { stroke: '#94a3b8' }
            }, eds)), [setEdges])}
          nodeTypes={nodeTypes}
          isValidConnection={useCallback((conn) => 
            conn.source !== conn.target && !edges.some(e => e.target === conn.target), [edges])}
          fitView
          defaultEdgeOptions={{ 
            type: 'smoothstep', 
            animated: true,
            style: { strokeWidth: 2 }
          }}
        />
      </div>
    </NodeUpdateContext.Provider>
  );
}
